package main

import (
	"brush/public"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/google/uuid"
	"log"
	"math/rand"
	"net/http"
	"sync"
	"time"
)

var (
	questions      []public.Question
	questionsMutex sync.RWMutex
)

// 初始化中间件
func setupMiddleware(app *fiber.App) {
	app.Use(cors.New(cors.Config{
		AllowOrigins: "*",
		AllowMethods: "GET,POST,PUT,DELETE,OPTIONS",
		AllowHeaders: "Origin,Content-Type,Accept",
	}))
	app.Use(securityHeaders())

}

// 根据ID获取题目
func getQuestionByID(c *fiber.Ctx) error {
	questionId := c.Params("id")
	if _, err := uuid.Parse(questionId); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"error": "无效的题目ID",
		})
	}

	q, err := public.GetQuestionByIDFromDB(questionId)
	if err != nil {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{
			"error": err.Error(),
		})
	}

	return c.JSON(q)
}

// 初始化路由
func setupRoutes(app *fiber.App) {
	api := app.Group("/api/v1")
	api.Use(middlewareTimeout(10 * time.Second))

	userGroup := api.Group("/users")
	{
		userGroup.Post("/register", registerUser)
		userGroup.Post("/login", loginUser)
	}

	questionGroup := api.Group("/questions")
	{
		questionGroup.Get("/random", getRandomQuestion)
		questionGroup.Post("/add", addQuestion)
		questionGroup.Get("/wrong-top10", getWrongTop10)
		questionGroup.Post("/:id/submit", submitAnswer)
		questionGroup.Get("/all", getAllQuestions)
		questionGroup.Get("/:id", getQuestionByID) // 新增路由：根据ID获取题目
	}

	practiceGroup := api.Group("/practice")
	{
		practiceGroup.Post("/submit", submitAnswer)
	}
}

func main() {
	app := fiber.New()
	setupMiddleware(app)
	setupRoutes(app)
	app.Static("/public", "./public")
	if err := public.InitDB(); err != nil {
		log.Fatalf("数据库初始化失败: %v", err)
	}

	log.Fatal(app.Listen(":36985"))
}

// 用户注册
func registerUser(c *fiber.Ctx) error {
	var newUser public.User
	if err := c.BodyParser(&newUser); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"error": "无法解析请求数据",
		})
	}
	newUser.ID = uuid.New().String()
	newUser.CreatedAt = time.Now()
	if err := public.AddUserToDB(newUser); err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"error": err.Error(),
		})
	}
	return c.JSON(fiber.Map{
		"message": "注册成功",
		"user":    newUser,
	})
}

// 用户登录
func loginUser(c *fiber.Ctx) error {
	type LoginRequest struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}
	var req LoginRequest
	if err := c.BodyParser(&req); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"error": "无法解析请求数据",
		})
	}
	user, err := public.GetUserByUsername(req.Username)
	if err != nil {
		return c.Status(http.StatusUnauthorized).JSON(fiber.Map{
			"error": "用户名或密码错误",
		})
	}
	if user.Password != req.Password {
		return c.Status(http.StatusUnauthorized).JSON(fiber.Map{
			"error": "用户名或密码错误",
		})
	}
	return c.JSON(fiber.Map{
		"message": "登录成功",
		"user":    user,
	})
}

// server.go

// 开始刷题模式
func startPracticeMode(c *fiber.Ctx) error {
	questions, err := public.GetAllQuestionsFromDB()
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"error": "获取题目时数据库操作出错",
		})
	}
	if len(questions) == 0 {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{
			"error": "数据库中没有题目",
		})
	}
	// 按顺序返回题目，不随机
	index := 0
	if index < len(questions) {
		question := questions[index]
		index++
		return c.JSON(question)
	}
	return c.Status(http.StatusNotFound).JSON(fiber.Map{
		"error": "没有更多题目了",
	})
}

// 获取所有题目
func getAllQuestions(c *fiber.Ctx) error {
	questions, err := public.GetAllQuestionsFromDB()
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"error": "获取题目时数据库操作出错",
		})
	}
	return c.JSON(questions)
}

// 添加新题目
func addQuestion(c *fiber.Ctx) error {
	type NewQuestionRequest struct {
		Content  string `json:"content"`
		Answer   string `json:"answer"`
		Category string `json:"category"`
	}
	var req NewQuestionRequest
	if err := c.BodyParser(&req); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"error": "无法解析请求数据",
		})
	}
	newQuestion := public.Question{
		ID:        uuid.New().String(),
		Content:   req.Content,
		Answer:    req.Answer,
		Category:  req.Category,
		CreatedAt: time.Now(),
	}
	if err := public.AddQuestionToDB(newQuestion); err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"error": err.Error(),
		})
	}
	return c.JSON(fiber.Map{
		"id": newQuestion.ID,
	})
}

// 获取随机题目
func getRandomQuestion(c *fiber.Ctx) error {
	questions, err := public.GetAllQuestionsFromDB()
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"error": "获取题目时数据库操作出错",
		})
	}
	if len(questions) == 0 {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{
			"error": "数据库中没有题目",
		})
	}
	// 权重计算（错题次数+1）
	totalWeight := 0
	for _, q := range questions {
		totalWeight += q.WrongCnt + 1
	}
	// 快速选择算法
	randomValue := rand.Intn(totalWeight)
	currentSum := 0
	for _, q := range questions {
		currentSum += q.WrongCnt + 1
		if randomValue < currentSum {
			return c.JSON(q)
		}
	}
	return c.JSON(questions[rand.Intn(len(questions))])
}

// 提交答案
func submitAnswer(c *fiber.Ctx) error {
	questionId := c.Params("id")
	if _, err := uuid.Parse(questionId); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"error": "无效的题目ID",
		})
	}
	type AnswerRequest struct {
		UserAnswer string `json:"userAnswer"`
	}
	var req AnswerRequest
	if err := c.BodyParser(&req); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"error": "无法解析请求数据",
		})
	}
	// 校验userAnswer是否为空
	if req.UserAnswer == "" {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"error": "答案不能为空",
		})
	}
	// 查询题目
	q, err := public.GetQuestionByIDFromDB(questionId)
	if err != nil {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{
			"error": err.Error(),
		})
	}
	// 检查答案
	correct := req.UserAnswer == q.Answer
	if !correct {
		// 更新错题计数
		if err := public.UpdateWrongCntInDB(questionId); err != nil {
			return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
				"error": err.Error(),
			})
		}
	}
	return c.JSON(fiber.Map{
		"correct": correct,
		"answer":  q.Answer,
	})
}

// 获取高频错题
func getWrongTop10(c *fiber.Ctx) error {
	wrongQuestions, err := public.GetTopWrongQuestionsFromDB(10)
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"error": err.Error(),
		})
	}
	return c.JSON(wrongQuestions)
}

// 安全头设置
func securityHeaders() fiber.Handler {
	return func(c *fiber.Ctx) error {
		c.Set("X-Content-Type-Options", "nosniff")
		c.Set("X-Frame-Options", "DENY")
		c.Set("Content-Security-Policy", "default-src 'self'")
		return c.Next()
	}
}

// 中间件：超时处理
func middlewareTimeout(timeout time.Duration) fiber.Handler {
	return func(c *fiber.Ctx) error {
		ch := make(chan struct{})
		go func() {
			defer close(ch)
			c.Next()
		}()

		select {
		case <-ch:
			return nil
		case <-time.After(timeout):
			return c.Status(http.StatusRequestTimeout).JSON(fiber.Map{
				"error": "请求超时",
			})
		}
	}
}
